package com.imooc.bilibili.aspect;

import com.imooc.bilibili.annotation.ApiLimitedRole;
import com.imooc.bilibili.auth.IUserRoleService;
import com.imooc.bilibili.domain.auth.UserRole;
import com.imooc.bilibili.exception.ConditionException;
import com.imooc.bilibili.support.UserSupport;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 切面
 *
 * 扩展，组概念
 * @author gcq
 * @Create 2022-06-01
 */
// 优先级
@Order(1)
// 注册为组件
@Component
// 切面
@Aspect
public class ApiLimitedRoleAspect {

    @Autowired
    private UserSupport userSupport;
    @Autowired
    private IUserRoleService userRoleService;

    // 包含指定注解
    @Pointcut("@annotation(com.imooc.bilibili.annotation.ApiLimitedRole)")
    public void check() {

    }

    /**
     * 请求之前
     * check() 符合织入点规则
     * @annotation(apiLimitedRole) 需要包含该注解
     */
    @Before("check() && @annotation(apiLimitedRole)")
    public void deBefore(JoinPoint joinPoint, ApiLimitedRole apiLimitedRole) {
        long userId = userSupport.getCurrentUserId();
        List<UserRole> userRoleList = userRoleService.getUserRoleByUserId(userId);
        String[] limitedRoleCodeList = apiLimitedRole.limitedRoleCodeList();
        // 当前方法角色编码
        Set<String> limitedRoleCodeSet = Arrays.stream(limitedRoleCodeList).collect(Collectors.toSet());
        // 当前用户角色编码
        Set<String> roleCodeSet = userRoleList.stream().map(UserRole::getRoleCode).collect(Collectors.toSet());
        // 和不允许的角色编码 交集有重合就不行
        roleCodeSet.retainAll(limitedRoleCodeSet);
        // 例如当前方法标注的角色编码为Lv0，请求该用户的角色编码也是Lv0，两个求并集数量数量为一 则不符合权限
        // 当前方法标注的角色编码为Lv0，请求用户的角色编码为Lv1 求并集为0 符合接口权限
        if(roleCodeSet.size() > 0) {
            throw new ConditionException("权限不足!");
        }
    }

}